package com.msg.service;

import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.msg.utils.MsgSrvUtils;
import com.pjc.config.BaseEnums;
import com.pjc.config.ErrorCode;
import com.pjc.config.GlobalKey;
import com.pjc.dao.SysMsgDao;
import com.pjc.dao.UserDao;
import com.pjc.dao.UserStatusDao;
import com.pjc.model.User;
import com.pjc.model.UserStatus;
import com.pjc.model.chat.SysMsg;
import com.pjc.rpc.LogicRpc;
import com.pjc.thrift.TInnerProto;
import com.pjc.utils.ConfigUtil;

/**
 * 消息登录验证类
 * 
 * @author 王畅
 * @since 2015年6月13日
 */
public class LoginService {

	protected static final Logger log = LoggerFactory.getLogger(LoginService.class);

	/**
	 * 登录验证
	 * 
	 * @param session
	 * @param userId
	 * @param data
	 * @throws Exception
	 */
	public static void loginHander(IoSession session, String userId, JSONObject data) throws Exception {

		String appId = data.getString("appId").toLowerCase();
		if (StringUtils.isEmpty(userId) || StringUtils.isBlank(userId)) {
			badLoginRequest(session, ErrorCode.USER_NOT_EXIST, appId);
			return;
		}
		User user = UserDao.getUser(userId, appId);
		if (user == null) {
			badLoginRequest(session, ErrorCode.USER_NOT_EXIST, appId);
			return;
		}
		boolean loginRst = false;
		JSONObject uJson = data.getJSONObject("data");
		int loginType = NumberUtils.toInt(data.getString("type"));
		switch (loginType) {
		case 1:
			/*
			 * String pwd = uJson.getString("pwd"); if
			 * ((!StringUtils.isEmpty(pwd)) && (user.getPwd().equals(pwd)))
			 */
			loginRst = true;
			break;
		case 2:
			String token = uJson.getString("token");
			if (!StringUtils.isEmpty(token))
				loginRst = true;
			break;
		default:
			loginRst = false;
		}
		if (!loginRst) {
			log.debug("登陆验证失败, userId:{}", userId);
			badLoginRequest(session, ErrorCode.USER_LOGIN_FAIL, appId);
			return;
		}
		/**************** 默认本服务器踢人 ********************************/
		if (MsgSrvUtils.existSession(userId, appId)) {
			kickUserHandler(userId, appId);
		}
		/**************** 跨服务器踢人 ***********************************/
		UserStatus userStatus = UserStatusDao.getUserStatus(userId, appId + ":user:status:");
		if (userStatus == null) {
			badLoginRequest(session, ErrorCode.USER_NOT_EXIST, appId);
			return;
		}
		if (userStatus.getServerId() != 0) {
			kictUserOnOtherSrv(userId, userStatus.getServerId(), appId);
		}
		User loginUser = UserDao.getUser(userId, appId);
		/************** session赋值 ************************/
		session.setAttribute("userId", userId);
		session.setAttribute("appId", appId);
		/*************** 添加session到缓存 ***********************************/
		MsgSrvUtils.addSession(session, userId, appId);
		/************* 设置当前用户所属服务 ***********************************/
		userStatus.setServerId(ConfigUtil.getInstance().getIntProperties("server.id"));
		/************* 添加用户对象到缓存 ***********************************/
		UserStatusDao.regist(userStatus, appId + ":user:status:");

		/************* 发送登录成功消息 ***********************************/
		session.write(ProtoBuilder.BuildLoginResult(201, ErrorCode.OK, appId));
		log.debug("Socket RemoteAddress:" + session.getRemoteAddress());
		if (session.getRemoteAddress() != null) {
			String remoteIp = session.getRemoteAddress().toString();
			updateUserOnlinesTatus(loginUser, 1, 0L, remoteIp, appId);
		}
		log.debug("应用ID【" + appId + "】,用户【" + userId + "】上次的离线时间:{}", loginUser.getLogoutTime());
		/***************************** 推送用户离线消息(类型推送) ******************************************/
		pushOfflineSysMsg(appId, session, userId, loginUser.getLogoutTime());
	}

	/**
	 * 推送离线的系统用户
	 * 
	 * @author 王畅
	 * @param appID
	 * @param session
	 * @param userId
	 * @param logoutTime
	 * @throws Exception
	 */
	private static void pushOfflineSysMsg(String appId, IoSession session, String userId, long logoutTime) throws Exception {
		List<SysMsg> list = SysMsgDao.getOfflineMsg(appId, userId, logoutTime);
		if ((list == null) || (list.size() == 0) || (list.isEmpty()))
			return;
		JSONObject msg = new JSONObject();
		msg.put("msgId", 203);

		JSONObject mJSON = getUserJson(appId, BaseEnums.SystemUser.Small_Secretary_User.getId());
		msg.put("fromUser", mJSON);

		JSONObject other = new JSONObject();
		other.put("hospName", "");
		other.put("img", "");

		msg.put("other", other);
		msg.put("appId", appId);
		msg.put("type", Integer.valueOf(BaseEnums.NoticeTypeEnum.Notice_OfflineData.getId()));
		msg.put("toUserId", userId);
		JSONArray arry = new JSONArray();
		for (SysMsg obj : list) {
			JSONObject json = new JSONObject();
			json.put("type", Integer.valueOf(obj.getType()));
			json.put("fromUser", obj.getFromUser());
			json.put("data", obj.getData());
			json.put("other", obj.getOther());
			json.put("time", Long.valueOf(obj.getTime()));
			arry.add(json);
		}
		msg.put("offlineData", arry);
		msg.put("time", Long.valueOf(System.currentTimeMillis()));
		boolean bool = MsgSrvUtils.write(session, msg);
		log.debug("[" + userId + "]发送离线系统消息：" + bool + ":" + msg);
	}

	/**
	 * 客户端
	 * 
	 * @param session
	 * @param returnCode
	 * @param appID
	 * @throws Exception
	 */
	private static void badLoginRequest(IoSession session, int returnCode, String appId) throws Exception {
		session.write(ProtoBuilder.BuildLoginResult(201, returnCode, appId));
		session.close(false);
	}

	/**
	 * 踢人
	 * 
	 * @param userId
	 * @param appID
	 * @throws Exception
	 */
	public static void kickUserHandler(String userId, String appId) throws Exception {
		IoSession session = MsgSrvUtils.delSession(userId, appId);
		UserStatusDao.unRegist(userId, appId + ":user:status:");
		if ((session == null) || (session.isClosing()) || (!session.isConnected())) {
			return;
		}
		long logoutTime = System.currentTimeMillis();

		boolean bl = UserDao.updateLogoutTime(userId, logoutTime, appId);
		if (!bl) {
			log.debug("应用ID【" + appId + "】,用户【" + userId + "】异常。更新下线时间失败, 更新下线时间：{}", Long.valueOf(logoutTime));

		}
		WriteFuture future = session.write(ProtoBuilder.BuildLoginResult(201, ErrorCode.USER_KICK_OUT, appId));
		future.awaitUninterruptibly();
		session.removeAttribute("userId");
		session.removeAttribute("appId", appId);
		session.close(false);
		session = null;
		log.debug("应用ID【" + appId + "】,用户【" + userId + "】异常重连或重复登陆踢下线, 更新下线时间：{}", Long.valueOf(logoutTime));
	}

	/**
	 * 超过间隔时间自动下线
	 * 
	 * @param appID
	 * @param session
	 * @param userId
	 * @param logoutTime
	 * @throws Exception
	 */
	public static void userLogout(String appId, IoSession session, String userId, long logoutTime) throws Exception {
		IoSession cacheSession = MsgSrvUtils.getSession(userId, appId);
		if ((cacheSession != null) && (cacheSession.getId() != session.getId()) && (cacheSession.getCreationTime() > session.getCreationTime()))
			return;
		MsgSrvUtils.delSession(userId, appId);
		UserStatusDao.unRegist(userId, appId + ":user:status:");
		boolean bl = UserDao.updateLogoutTime(userId, logoutTime, appId);
		if (!bl) {
			log.debug("应用ID【" + appId + "】,用户【" + userId + "】异常。更新下线时间失败, 更新下线时间：{}", Long.valueOf(logoutTime));

		}
		User user = UserDao.getUser(userId, appId);
		String ip = (session.getRemoteAddress() == null) ? "" : session.getRemoteAddress().toString();
		updateUserOnlinesTatus(user, 0, logoutTime - session.getCreationTime(), ip, appId);
	}

	/**
	 * 更新用户在线信息
	 * 
	 * @param loginUser
	 * @param online
	 * @param onlineTime
	 * @param ip
	 * @param appID
	 * @throws Exception
	 */
	public static void updateUserOnlinesTatus(User user, int online, long onlineTime, String ip, String appId) throws Exception {
		boolean bl = UserDao.updateUserOnlineStatus(user.getUserId(), online, onlineTime, appId);
		String status = online == 0 ? "下线" : "上线";
		if (bl) {
			log.error("用户【" + user.getUserId() + "】,当前状态【" + status + "】,更新用户信息成功.");
		}
		writeLoginLog(appId, user, online, onlineTime, ip);
	}

	/**
	 * 日志记录
	 * 
	 * @author 王畅
	 * @param appID
	 * @param user
	 * @param online
	 * @param onLineTime
	 * @param ip
	 * @throws Exception
	 */
	public static void writeLoginLog(String appId, User user, int online, long onLineTime, String ip) throws Exception {
	}

	/**
	 * 系统消息推送用户信息
	 * 
	 * @author 王畅
	 * @param appID
	 * @param userID
	 * @return
	 * @throws Exception
	 */
	private static JSONObject getUserJson(String appId, String userId) throws Exception {
		JSONObject mJSON = new JSONObject();
		User managerUser = UserDao.getUser(userId, appId);
		if (managerUser == null) {
			mJSON.put("userId", userId);
			mJSON.put("uname", BaseEnums.SystemUser.Small_Secretary_User.getDesc());
		} else {
			mJSON.put("userId", Integer.valueOf(managerUser.getUserId()));
			mJSON.put("uname", (managerUser.getUserName() == null) ? "" : managerUser.getUserName());
		}
		return mJSON;
	}

	/**
	 * 调用逻辑服务器查找
	 * 
	 * @author 王畅
	 * @param userId
	 * @param srvId
	 * @param appID
	 */
	private static void kictUserOnOtherSrv(String userId, int srvId, String appId) {
		TInnerProto proto = new TInnerProto();
		proto.setId(GlobalKey.AccessToLogic.KICK_USER);
		JSONObject json = new JSONObject();
		json.put("userId", userId);
		json.put("appId", appId);
		json.put("serverId", Integer.valueOf(srvId));
		proto.setData(json.toString());
		proto.setFromSrv(MsgSrvUtils.serverId);
		LogicRpc.getInstance().send(proto);
	}
}
